//
// @Auther: by wujehy
// @Email:wujehy@qq.com
// @Data:20-4-29
// @Time:下午3:11
//



#include <iostream>
#include <string.h>
#include <map>
#include <getopt.h>
#include <algorithm>
#include <Business/internaltypes.h>
#include "Tools/sockcompat.h"
#include "Tools/ParsingArgs.h"
#include <GeeJoan/NetWorkPackage.pb.h>
#include <GeeJoan/AuthModule.pb.h>
#include <GeeJoan/IoTModule.pb.h>
#include <GeeJoan/ErrorModule.pb.h>
#include <chrono>
#include <Tools/CommonTool.h>

#define MAX_PARAM 50
#define MAXLINE 1024
#define GEEJOAN_VERSION "1.6"
using namespace GeeJoan::Protocol;

/**
 * 命令行 函数指针
 */
typedef int (*CommandFunction)(int fd, std::string &commandLine);

typedef NetWork::NetWorkPackageModel ModType;

/**
 * @brief 获取 指令类型 , 即 第一个 单词
 * @param str 输入 本次解析的 字符串
 * @return 返回结果
 */
int getCommandType(std::string &instr, std::string &outType, std::string &paramList);

static void handle_connection(int sockfd);

std::map<std::string, CommandFunction> funcMap;


std::string username;
std::string token;
int64_t taskid_ = 1;

int64_t getTimeMicro()
{
    std::chrono::time_point<std::chrono::system_clock> p = std::chrono::system_clock::now();
    return std::chrono::duration_cast<std::chrono::microseconds>( p.time_since_epoch()).count();
}


int64_t getTimeMilli()
{
    return getTimeMicro() / 1000;
}

template<class T>
void sendNetWorkPackage(int fd, NetWork::NetWorkPackageModel mod, int subType, T data)
{
    NetWork::NetWorkPackageRequest netWorkPackageRequest;
    netWorkPackageRequest.set_type_m( mod );
    netWorkPackageRequest.set_type_sub( subType );
    netWorkPackageRequest.set_taskid( taskid_++ );
    netWorkPackageRequest.set_body( data.SerializeAsString());
    std::string sendNetworkPackage;
    netWorkPackageRequest.SerializePartialToString( &sendNetworkPackage );
    write( fd, sendNetworkPackage.c_str(), sendNetworkPackage.length());
}

int VersionFunction(int fd, std::string &commandLine)
{
    std::cout <<"Version "<<GEEJOAN_VERSION <<" power by wujehy"<<std::endl;
    return 0;
}
int LoginFunction(int fd, std::string &commandLine)
{
    std::string username, password;

    std::map<std::string, std::vector<std::string> > result;
    ParsingArgs pa;
    pa.AddArgType( 'u', "username", ParsingArgs::MAYBE_VALUE );
    pa.AddArgType( 'p', "password", ParsingArgs::MAYBE_VALUE );

    std::string errPos = "";

    int iRet = pa.Parse( commandLine, result, errPos );

    if (0 > iRet)
    {
        std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
    } else
    {
        std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
        for (; it != result.end(); ++it)
        {
            if (it->first == "u" || it->first == "username")
            {
                for (int i = 0; i < it->second.size(); ++i)
                {
                    username = it->second[i];
                    break;
                }
            }

            if (it->first == "p" || it->first == "password")
            {
                for (int i = 0; i < it->second.size(); ++i)
                {
                    password = it->second[i];
                    break;
                }
            }
        }
    }

//    std::cout << "username = "<<username << " , password = "<< password <<std::endl;

    if (username.empty() || password.empty())
    {
        // 空
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }

    // 成功
    Auth::LoginRequest loginRequest;
    loginRequest.set_username( username );
    loginRequest.set_password( password );
    loginRequest.set_timestamp( getTimeMilli());
    sendNetWorkPackage( fd, ModType::AuthMod, AUTH_LOGIN, loginRequest );
    return 0;
}


int LogoutFunction(int fd, std::string &commandLine)
{
    Auth::LogoutAPI logoutApi;
    logoutApi.set_token( token );
    logoutApi.set_timestamp( getTimeMilli());
    sendNetWorkPackage( fd, ModType::AuthMod, AUTH_LOGOUT, logoutApi );
    return 0;
}

int GetCurrentTimeFunction(int fd, std::string &commandLine)
{
    std::cout <<"currentTime : "<<YELLOW << getTimeMilli() << RESET <<std::endl;
    return 0;
}

int HelpFunction(int fd, std::string &commandLine)
{
    std::cout << "Command List: " << std::endl;
//    register
//    ( "login", LoginFunction ));
//    ( "logout", LogoutFunction ));
//    ( "help", HelpFunction ));
//    ( "register", RegisterFunction ));
//    ( "changepassword", ChangePassword ));
//    ( "control", ControlDeviceFunction ));
//    ( "controlack", ControlDeviceAckFunction ));
//    ( "devicelogin", LoginDeviceFunction ));
//    ( "generatedevicetoken", GenerateDeviceTokenFunction ));
//    ( "findgateway", FindGatewayFunction ));
//    ( "createdevice", CreateDeviceFunction ));
//    ( "upload", UploadDataFunction ));
//    ( "timenow", GetCurrentTimeFunction));
//    ( "find", FindDatasFunction));
//    ( "version", VersionFunction));
    std::cout <<YELLOW <<"Auth Mod :"<<RESET<<std::endl;
    std::cout <<"Register -u [username] -p [password] -e [email]"<<std::endl;
    std::cout <<"Login -u [username] -p [password]"<<std::endl;
    std::cout <<"Logout"<<std::endl;
    std::cout <<"ChangePassword -p [password]"<<std::endl;
    std::cout <<"register --username [username] --password [password] --email [email]"<<std::endl;
    std::cout <<"login --username [username] --password [password]"<<std::endl;

    std::cout <<YELLOW <<"IOT Mod :"<<RESET<<std::endl;
    std::cout <<"DeviceLogin -t [deviceToken] "<<std::endl;
    std::cout <<"FindGateway -t [DeviceToken] "<<std::endl;
    std::cout <<"CreateDevice -n [note] -g [gatewayid] -p [permission]"<<std::endl;
    std::cout <<"GenerateDeviceToken -g [gatewayid] -d [deviceid]"<<std::endl;

    std::cout <<"Control -t [DeviceToken] -d [data]"<<std::endl;
    std::cout <<"ControlAck -t [taskCode] -m [errmsg] -c [errcode]"<<std::endl;
    std::cout <<"find -g [gatewayid] -d [deviceid] -k [key]"<<std::endl;
    std::cout <<"upload -g [gatewayid] -d [deviceid] -k [key] -p [permission] "<<std::endl;


    std::cout <<YELLOW <<"Other Mod :"<<RESET<<std::endl;
    std::cout <<"help "<<std::endl;
    std::cout <<"version "<<std::endl;
    std::cout <<"timenow "<<std::endl;
    return 0;
}

int RegisterFunction(int fd, std::string &commandLine)
{

    std::string username, password, email;

    std::map<std::string, std::vector<std::string> > result;
    ParsingArgs pa;
    pa.AddArgType( 'u', "username", ParsingArgs::MAYBE_VALUE );
    pa.AddArgType( 'p', "password", ParsingArgs::MAYBE_VALUE );
    pa.AddArgType( 'e', "email", ParsingArgs::MAYBE_VALUE );
//    pa.AddArgType(' '," ", ParsingArgs::MAYBE_VALUE);

    std::string errPos = "";

    int iRet = pa.Parse( commandLine, result, errPos );

    if (0 > iRet)
    {
        std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
    } else
    {
        std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
        for (; it != result.end(); ++it)
        {
            if (it->first == "u" || it->first == "username")
            {
                for (int i = 0; i < it->second.size(); ++i)
                {
                    username = it->second[i];
                    break;
                }
            }

            if (it->first == "p" || it->first == "password")
            {
                for (int i = 0; i < it->second.size(); ++i)
                {
                    password = it->second[i];
                    break;
                }
            }

            if (it->first == "e" || it->first == "email")
            {
                for (int i = 0; i < it->second.size(); ++i)
                {
                    email = it->second[i];
                    break;
                }
            }
        }
    }

    if (username.empty() || password.empty() || email.empty())
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }

    Auth::RegisterAPI registerApi;
    registerApi.set_username( username );
    registerApi.set_email( email );
    registerApi.set_password( password );
    sendNetWorkPackage( fd, ModType::AuthMod, AUTH_REGISTER, registerApi );

    return 0;
}

int ChangePassword(int fd, std::string &commandLine)
{
    std::string newPassword;

    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 'p', "password", ParsingArgs::MAYBE_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {
                if (it->first == "p" || it->first == "password")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        newPassword = it->second[i];
                        break;
                    }
                }
            }
        }
    }

    if (token.empty() || newPassword.empty())
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }
    // 成功
    Auth::ChangePasswordRequest changePasswordRequest;
    changePasswordRequest.set_oldtoken( token );
    changePasswordRequest.set_newpassword( newPassword );
    changePasswordRequest.set_timestamp( getTimeMilli());
    sendNetWorkPackage( fd, ModType::AuthMod, AUTH_CHANGE_PASSWORD, changePasswordRequest );
    return 0;
}

int LoginDeviceFunction(int fd, std::string &commandLine)
{
    std::string inputToken;

    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 't', "token", ParsingArgs::MAYBE_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {
                if (it->first == "t" || it->first == "token")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        inputToken = it->second[i];
                        break;
                    }
                }
            }
        }
    }

    if (inputToken.empty())
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }

    IoT::LoginDeviceAPI loginDeviceApi;
    loginDeviceApi.set_token( inputToken );
    loginDeviceApi.set_time( getTimeMilli());

    sendNetWorkPackage( fd, ModType::IOTMod, IOT_LOGIN_DEVICE, loginDeviceApi );
    return 0;
}

int UploadDataFunction(int fd, std::string &commandLine){

    uint64_t GatewayId = 0 , DevideId = 0;
    int32_t  permission = 0  , key = 0 ;

    std::string sensorData , deviceToken ;
    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 'g', "gatewayid", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'd', "deviceid", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'D', "data", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'p', "permission", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'k', "key", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 't', "token", ParsingArgs::MAYBE_VALUE );


        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {


                if (it->first == "d" || it->first == "deviceid")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        DevideId = atoll(it->second[i].c_str());
                        break;
                    }
                }

                if (it->first == "D" || it->first == "data")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        sensorData = it->second[i];
                        break;
                    }
                }

                if (it->first == "t" || it->first == "token")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        deviceToken = it->second[i];
                        break;
                    }
                }

                if (it->first == "g" || it->first == "gatewayid")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        GatewayId = atoll(it->second[i].c_str());
                        break;
                    }
                }

                if (it->first == "k" || it->first == "key")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        key = atoll(it->second[i].c_str());
                        break;
                    }
                }

                if (it->first == "p" || it->first == "permission")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        permission = atoll(it->second[i].c_str());
                        break;
                    }
                }
            }
        }
    }



    if ( GatewayId == 0 || DevideId ==0 )
    {
        std::cout << RED << " Parameter error , GatewayId or DevideId is empty " << RESET << std::endl;
        return -1;
    }

    if (key == 0 )
    {

    }

    // 成功

    if (permission == 0 )
    {
        permission = 4 ;
    }

    IoT::UploadSensorDataAPI uploadSensorDataApi;
    uploadSensorDataApi.set_gatewayid(GatewayId);
    uploadSensorDataApi.set_devideid(DevideId);
    uploadSensorDataApi.set_permission((IoT::DataPermissionEnum)permission);
    uploadSensorDataApi.set_key(key);
    uploadSensorDataApi.set_data(sensorData);
    uploadSensorDataApi.set_token(deviceToken);

    sendNetWorkPackage(fd , ModType::IOTMod , IOT_UPLOAD_SENSOR_DATA , uploadSensorDataApi);
    return 0;
}

int FindDatasFunction(int fd, std::string &commandLine){

    uint64_t GatewayId = 0 , DevideId = 0;
    int32_t  key = 0 , size = 0 ;

    int64_t currentTime = 0 ;
    IoT::FindDirectionEnum direction = IoT::FindDirectionEnum::FindDirectionEnum_Undefinition;

    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 'g', "gatewayid", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'd', "deviceid", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'k', "key", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 's', "size", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 't', "time", ParsingArgs::MAYBE_VALUE );
//        pa.AddArgType( 't', "token", ParsingArgs::MAYBE_VALUE );

        pa.AddArgType( 'b', "before", ParsingArgs::NO_VALUE );
        pa.AddArgType( 'a', "after", ParsingArgs::NO_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {

                if (it->first == "a" || it->first == "after")
                {
                    direction =  IoT::FindDirectionEnum_After ;
                    continue;
                }

                if (it->first == "b" || it->first == "before")
                {
                    direction = IoT::FindDirectionEnum_Before ;
                    continue;
                }



                if (it->first == "d" || it->first == "deviceid")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        DevideId = (uint64_t)atoll(it->second[i].c_str());
                        break;
                    }
                }

                if (it->first == "g" || it->first == "gatewayid")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        GatewayId = (uint64_t)atoll(it->second[i].c_str());
                        break;
                    }
                }

                if (it->first == "k" || it->first == "key")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        key = atoi(it->second[i].c_str());
                        break;
                    }
                }


                if (it->first == "s" || it->first == "size")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        size = atoi(it->second[i].c_str());
                        break;
                    }
                }


                if (it->first == "t" || it->first == "time")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        currentTime = atoll(it->second[i].c_str());
                        break;
                    }
                }
            }
        }
    }



    if ( GatewayId == 0 || DevideId ==0 )
    {
        std::cout << RED << " Parameter error , GatewayId or DevideId is empty " << RESET << std::endl;
        return -1;
    }

    if (key == 0 && (direction == IoT::FindDirectionEnum_Undefinition|| currentTime == 0 )){
        std::cout << RED << " Parameter error , direction and time not set " << RESET << std::endl;
        return -1;
    }

    // 成功

    IoT::FindSensorDataRequest findSensorDataRequest;
    findSensorDataRequest.set_token( token );
    findSensorDataRequest.set_gatewayid( GatewayId );
    findSensorDataRequest.set_devideid( DevideId );
    findSensorDataRequest.set_key( key );

    findSensorDataRequest.set_direction( direction );
    findSensorDataRequest.set_size( size );

    findSensorDataRequest.set_time( currentTime );

    sendNetWorkPackage(fd , ModType::IOTMod , IOT_FIND_SENSOR_DATA , findSensorDataRequest);
    return 0;
}
int ControlDeviceFunction(int fd, std::string &commandLine)
{
    std::string controlToken, controlData;

    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 't', "token", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'd', "data", ParsingArgs::MAYBE_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {
                if (it->first == "t" || it->first == "token")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        controlToken = it->second[i];
                        break;
                    }
                }

                if (it->first == "d" || it->first == "data")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        controlData = it->second[i];
                        break;
                    }
                }
            }
        }
    }

    if (controlToken.empty() || controlData.empty())
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }

    IoT::ControlDeviceRequest controlDeviceRequest;
    controlDeviceRequest.set_token( controlToken );
    controlDeviceRequest.set_data( controlData );
    sendNetWorkPackage( fd, ModType::IOTMod, IOT_CONTROL_DEVICE, controlDeviceRequest );
    return 0;
}

int ControlDeviceAckFunction(int fd, std::string &commandLine)
{
    std::string taskCode, errmsg;
    int64_t errCode = 0;

    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 't', "task", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'm', "msg", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'c', "code", ParsingArgs::MAYBE_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {
                if (it->first == "t" || it->first == "task")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        taskCode = it->second[i];
                        break;
                    }
                }

                if (it->first == "m" || it->first == "msg")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        errmsg = it->second[i];
                        break;
                    }
                }


                if (it->first == "c" || it->first == "code")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        errCode = atol( it->second[i].c_str());
                        break;
                    }
                }
            }
        }
    }

    if (taskCode.empty() || errmsg.empty() || errCode == 0)
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }

    IoT::ControlDeviceAckAPI controlDeviceAckApi;
    controlDeviceAckApi.set_taskcode( taskCode );
    controlDeviceAckApi.set_errcode( errCode );
    controlDeviceAckApi.set_errormsg( errmsg );

    sendNetWorkPackage( fd, ModType::IOTMod, IOT_CONTROL_ACK, controlDeviceAckApi );
    return 0;

}
//GenerateDeviceToken

int FindGatewayFunction(int fd, std::string &commandLine){

    std::string deviceToken  ;
    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 't', "token", ParsingArgs::MAYBE_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {

                if (it->first == "t" || it->first == "token")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        deviceToken =  it->second[i] ;
                        break;
                    }
                }
            }
        }
    }

    if (deviceToken.empty())
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }


    IoT::FindGatewayRequest findGatewayRequest;

    findGatewayRequest.set_token( deviceToken );

    sendNetWorkPackage(fd , ModType::IOTMod , IOT_FIND_GATEWAY , findGatewayRequest);
    return 0;
}
int CreateDeviceFunction(int fd, std::string &commandLine){
    std::string note;
    uint64_t gatewayid = 0;
    int32_t permission = 0;

    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 'g', "gateway", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'p', "permission", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'n', "note", ParsingArgs::MAYBE_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {


                if (it->first == "p" || it->first == "permission")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        permission = atol( it->second[i].c_str());
                        break;
                    }
                }


                if (it->first == "g" || it->first == "gateway")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        gatewayid = atol( it->second[i].c_str());
                        break;
                    }
                }


                if (it->first == "n" || it->first == "note")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        note =  it->second[i] ;
                        break;
                    }
                }
            }
        }
    }

    if (gatewayid == 0 )
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }


    if (permission == 0 )
    {
        permission = 4 ;
    }

    IoT::CreateDeviceRequest createDeviceRequest;
    createDeviceRequest.set_gatewayid( gatewayid );
    createDeviceRequest.set_note( note );
    createDeviceRequest.set_permission((IoT::DataPermissionEnum) permission );
    sendNetWorkPackage( fd, ModType::IOTMod, IOT_CONTROL_DEVICE, createDeviceRequest );
    return 0;

}
int GenerateDeviceTokenFunction(int fd, std::string &commandLine)
{
    uint64_t gatewayid = 0;
    uint64_t deviceid = 0;

    {
        std::map<std::string, std::vector<std::string> > result;
        ParsingArgs pa;
        pa.AddArgType( 'g', "gateway", ParsingArgs::MAYBE_VALUE );
        pa.AddArgType( 'd', "device", ParsingArgs::MAYBE_VALUE );

        std::string errPos = "";

        int iRet = pa.Parse( commandLine, result, errPos );

        if (0 > iRet)
        {
            std::cout << "Parameter processing error : " << iRet << errPos << std::endl;
        } else
        {
            std::map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for (; it != result.end(); ++it)
            {


                if (it->first == "d" || it->first == "device")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        deviceid = atol( it->second[i].c_str());
                        break;
                    }
                }


                if (it->first == "g" || it->first == "gateway")
                {
                    for (int i = 0; i < it->second.size(); ++i)
                    {
                        gatewayid = atol( it->second[i].c_str());
                        break;
                    }
                }
            }
        }
    }

    if (gatewayid == 0 || deviceid == 0)
    {
        std::cout << RED << " Parameter error " << RESET << std::endl;
        return -1;
    }

    IoT::GenerateDeviceTokenRequest generateDeviceTokenRequest;

    generateDeviceTokenRequest.set_token( token );
    generateDeviceTokenRequest.set_gatewayid( gatewayid );
    generateDeviceTokenRequest.set_devideid( deviceid );

    sendNetWorkPackage( fd, ModType::IOTMod, IOT_GENERATE_DEVICE_TOKEN, generateDeviceTokenRequest );
    return 0;

}



void init()
{
    // 注册事件

    funcMap.insert( std::pair<std::string, CommandFunction>( "login", LoginFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "logout", LogoutFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "help", HelpFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "register", RegisterFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "changepassword", ChangePassword ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "control", ControlDeviceFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "controlack", ControlDeviceAckFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "devicelogin", LoginDeviceFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "generatedevicetoken", GenerateDeviceTokenFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "findgateway", FindGatewayFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "createdevice", CreateDeviceFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "upload", UploadDataFunction ));
    funcMap.insert( std::pair<std::string, CommandFunction>( "timenow", GetCurrentTimeFunction));
    funcMap.insert( std::pair<std::string, CommandFunction>( "find", FindDatasFunction));
    funcMap.insert( std::pair<std::string, CommandFunction>( "version", VersionFunction));

}

int main(int argc, char *argv[])
{
    int connfd = 0;
    int clen = 0;
    struct sockaddr_in client;
    if (argc < 2)
    {
        printf( "Uasge: %s [server IP address] [port]\n", argv[0] );
        return -1;
    }
    int port = atoi( argv[2] );
    if (port <= 0)
    {
        perror( "port error" );
        return -1;
    }
    client.sin_family = AF_INET;
    client.sin_port = htons( port );
    client.sin_addr.s_addr = inet_addr( argv[1] );
    connfd = socket( AF_INET, SOCK_STREAM, 0 );
    if (connfd < 0)
    {
        perror( "socket" );
        return -1;
    }

    if (connect( connfd, (struct sockaddr *) &client, sizeof( client )) < 0)
    {
        perror( "connect" );
        return -1;
    }

    std::cout << "client Run ... " << std::endl;
    std::cout << "input " << RED << "`help`" << RESET << " open Command List ... " << std::endl;

    handle_connection( connfd );
    google::protobuf::ShutdownProtobufLibrary();
    return 0;
}


int getCommandType(std::string &instr, std::string &outType, std::string &paramList)
{

    int type_start = 0, type_end = 0;
    int param_start = 0;
    int result = 0;

    size_t n = instr.find_last_not_of( " \r\n\t" );
    if (n != std::string::npos)
    {
        instr.erase( n + 1, instr.length() - n );
    }


    for (int i = 0; i < instr.length(); ++i)
    {
        if ((instr.at( i ) >= 'a' && instr.at( i ) <= 'z') || (instr.at( i ) >= 'A' && instr.at( i ) <= 'Z'))
        {
            type_start = i;
            break;
        }
    }

    for (int j = type_start; j < instr.length(); ++j)
    {
        if (instr.at( j ) == ' ')
        {
            type_end = j;
            outType = instr.substr( type_start, type_end );
            break;
        }
    }

    if (type_end == 0)
    {
        type_end = instr.length();
        outType = instr.substr( type_start, type_end );
    }
    result = 1;
    for (int k = type_end; k < instr.length(); ++k)
    {
        if (instr.at( k ) == '-')
        {
            param_start = k;
            result = 2;
            break;
        }
    }

    if (param_start > 0)
    {
        paramList = instr.substr( param_start, instr.length());
    }

    //
    return result;

}


/**
 * @brief 回包事件
 * @param data 数据
 * @param len  数据长度
 * @return
 */
int ResposePackageEvent(uint8_t *data, int len)
{

    NetWork::NetWorkPackageRespose networkPackageResp;
    if (!networkPackageResp.ParseFromArray( data, len ))
    {
        // 不支持
        write( STDOUT_FILENO, "proto deserial error\r\n", 22 );

    } else
    {
        //支持的类型
        std::cout << YELLOW << "Respose : code = " << networkPackageResp.code()
                  << ", mod = " << networkPackageResp.type_m() << " , type = " << networkPackageResp.type_sub()
                  << " , taskid = " << networkPackageResp.taskid()
                  << " , body = " << StringToHex( networkPackageResp.body()) << RESET << std::endl;
    }
//            std::cout << " taskid resp = " << networkPackageResp.taskid() << std::endl;

    if (networkPackageResp.code() == 500)
    {
        Error::ErrorMessage errorMessage;

        if (errorMessage.ParseFromString( networkPackageResp.body()))
        {
            std::cout << RED << "ErrorMsg : " << errorMessage.errmsg() << RESET << std::endl;
        }

    }

    if (networkPackageResp.code() != 200)
    {
        return -1;
    }

    if (networkPackageResp.type_m() == NetWork::NetWorkPackageModel::AuthMod)
    {
        switch (networkPackageResp.type_sub())
        {
            case 1:
            {
                if (networkPackageResp.code() == 200)
                {
                    std::cout << "Register " << GREEN << "Success !" << RESET << std::endl;
                }
                break;
            }
            case 2:
            {
                Auth::LoginRespose loginRespose;
                if (loginRespose.ParseFromArray( networkPackageResp.body().c_str(),
                                                 networkPackageResp.body().length()));
                {
                    // 解包成功
                    token = loginRespose.token();
                    std::cout << "Login " << GREEN << "Success " << RESET << std::endl;
                    std::cout << "Your Token = " << GREEN << token << RESET << std::endl;
                }
                break;
            }

            case 3:
            {
                std::cout << " Logout " << GREEN << "Success " << RESET << networkPackageResp.code() << std::endl;
                break;
            }

            case 4:
            {
                std::cout << " head code = " << networkPackageResp.code() << std::endl;
                break;
            }
            case 5:
            {
                std::cout << "change code = " << networkPackageResp.code() << std::endl;
                Auth::ChangePasswordRespose changePasswordRespose;
                if (changePasswordRespose.ParseFromArray( networkPackageResp.body().c_str(),
                                                          networkPackageResp.body().length()))
                {
                    token = changePasswordRespose.newtoken();
                    std::cout << "your new token = " << GREEN << token << RESET << std::endl;
                }
                break;
            }
        }
    } else if (networkPackageResp.type_m() == NetWork::NetWorkPackageModel::IOTMod)
    {
        switch (networkPackageResp.type_sub())
        {
            case 1:
            {
                std::cout << "Upload Data : " << GREEN << " Success " << RESET << std::endl;
                break;
            }
            case 2:
            {
                std::cout << "FindData : " << GREEN << " Success " << RESET << std::endl;
                IoT::FindSensorDataRespose findSensorDataRespose;

                if (!findSensorDataRespose.ParseFromString( networkPackageResp.body()))
                {
                    // 解析失败
                    std::cout << RED << "ERROR : deserial findSensorDataRespose Fail ! " << RESET << std::endl;
                    break;
                }

                // 解析成功
                std::cout << "Find Data : gatewayid = " << YELLOW << findSensorDataRespose.gatewayid() << RESET
                          << ", devideid  = " << YELLOW << findSensorDataRespose.devideid() << RESET
                          << ", size = " << YELLOW << findSensorDataRespose.datas().size() << RESET << std::endl;
                for (int i = 0; i < findSensorDataRespose.datas().size(); ++i)
                {
                    std::string tempData = findSensorDataRespose.datas( i ).data();
                    std::cout << "Datas[" << i << "]"
                              << " : key = " << YELLOW << findSensorDataRespose.datas( i ).key() << RESET
                              << " , data(Src) = " << YELLOW << tempData << RESET
                              << " , data(HEX) = " << YELLOW << StringToHex( tempData ) << RESET
                              << " , time = " << YELLOW << findSensorDataRespose.datas( i ).time() << RESET
                              << std::endl;
                }
                break;
            }

            case IOT_CONTROL_DEVICE:
            {
//                std::cout << " control code = " << networkPackageResp.code() << std::endl;
                std::cout << " Control Send : " << GREEN << "SUCCESS" << RESET << std::endl;
                break;
            }

            case IOT_CONTROL_LISTERNER:
            {
//                std::cout << " lister code = " << networkPackageResp.ode() << std::endl;
                IoT::ControlDeviceListerner controlDeviceListerner;

                if (!controlDeviceListerner.ParseFromString( networkPackageResp.body()))
                {
                    std::cout << RED << "ERROR : deserial controlDeviceListerner Fail ! " << RESET << std::endl;
                    break;
                }

                std::cout << "ListernerEvent : taskCode = " << YELLOW << controlDeviceListerner.taskcode() << RESET
                          << " , data = " << YELLOW << controlDeviceListerner.data() << RESET
                          << " , time = " << YELLOW << controlDeviceListerner.time() << RESET << std::endl;

                break;
            }


            case IOT_CONTROL_ACK:
            {
                std::cout << "Ack : " << GREEN << "SUCCESS " << RESET << std::endl;
                break;
            }
            case IOT_CONTROL_ACK_LISTERNER:
            {
                IoT::ControlDeviceAckListerner controlDeviceAckListerner;
                if (!controlDeviceAckListerner.ParseFromString( networkPackageResp.body()))
                {
                    std::cout << RED << "ERROR : deserial controlDeviceAckListerner Fail ! " << RESET << std::endl;
                    break;
                }

                std::cout << "AckEvent : taskCode = " << YELLOW << controlDeviceAckListerner.taskcode() << RESET
                          << " , errcode = " << YELLOW << controlDeviceAckListerner.errcode() << RESET
                          << " , errormsg = " << YELLOW << controlDeviceAckListerner.errormsg() << RESET
                          << " , time = " << YELLOW << controlDeviceAckListerner.time() << RESET << std::endl;
                break;
            }
            case IOT_FIND_GATEWAY:
            {
                IoT::FindGatewayRespose findGatewayRespose;
                if (findGatewayRespose.ParseFromString( networkPackageResp.body()))
                {
                    for (int i = 0; i < findGatewayRespose.gatewayid().size(); ++i)
                    {
                        std::cout << " your gatewayids[" << i << "] = " << GREEN
                                  << findGatewayRespose.gatewayid().at( i ) << RESET << std::endl;
                    }
                }
                break;
            }

            case IOT_CREATE_DEVICE:
            {
                IoT::CreateDeviceRespose createDeviceRespose;

                if (createDeviceRespose.ParseFromString( networkPackageResp.body()))
                {
                    std::cout << " your Device id = " << GREEN << createDeviceRespose.devideid() << RESET << std::endl;
                }
                break;
            }

            case IOT_GENERATE_DEVICE_TOKEN:
            {
                IoT::GenerateDeviceTokenRespose generateDeviceTokenRespose;
                if (generateDeviceTokenRespose.ParseFromString( networkPackageResp.body()))
                {
                    std::cout << " your new Token = " << GREEN << generateDeviceTokenRespose.token() << RESET
                              << std::endl;
                }
            }

        }
    } else if (networkPackageResp.type_m() == NetWork::NetWorkPackageModel::UNDEFINE)
    {
        switch (networkPackageResp.type_sub())
        {
            case 0:
            {
                std::cout << " Link Server " << GREEN << " Success " << RESET << std::endl;
            }
        }
    } else
    {
        // undefine
    }
    return 0;
}


static void handle_connection(int sockfd)
{
    char sendline[MAXLINE], recvline[MAXLINE];

    init();
    std::string inputCommand;
    std::string sendProtocolPackage;
    struct pollfd pfds[2];
    int n;
    pfds[0].fd = sockfd;
    pfds[0].events = POLLIN;
    pfds[1].fd = STDIN_FILENO;
    pfds[1].events = POLLIN;

    while (1)
    {
        //nfds：用来指定第一个参数数组元素个数: 2
        poll( pfds, 2, -1 );
        if (pfds[0].revents & POLLIN)
        {
            n = read( sockfd, recvline, MAXLINE );
            if (n == 0)
            {
                fprintf( stderr, "client: server is closed.\n" );
                close( sockfd );
            }
            // printf("recvline: %s", recvline);
            ResposePackageEvent((uint8_t *) recvline, n );
            // std::cout <<BOLDGREEN<<"client>>"<<RESET<<std::endl;
            write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m", sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );
        }
        if (pfds[1].revents & POLLIN)
        {
            // 命令行输入事件
            n = read( STDIN_FILENO, sendline, MAXLINE );
            inputCommand.clear();

            inputCommand = std::string( sendline, n );

            std::string cmdType, cmdParam; // = getCommandType(inputCommand);
            cmdType.clear();
            cmdParam.clear();
            if (getCommandType( inputCommand, cmdType, cmdParam ) < 1)
            {
                //参数解析失败
                std::cout << " error param " << std::endl;
                continue;
            }

            std::transform( cmdType.begin(), cmdType.end(), cmdType.begin(), ::tolower );

            if (cmdType == "quit")
            {
                break;
            }

            auto findFunction = funcMap.find( cmdType );
            if (findFunction != funcMap.end())
            {
                // 命令存在
                findFunction->second( sockfd, cmdParam );
            } else
            {
                // 不存在
                std::cout << " command undefine " << std::endl;
            }
            write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m", sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );
        }
    }
}
